using DA.AnimGraph;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace DA.AnimGraph.Editor {

    // 编辑文件
    public class AnimGraphArchiveAsset : ScriptableObject {
        public AUID uuid; // 就是 AGA_Root.uuid，方便观察和查询。注意要同步修改二者
        public AUID[] graphUuid; // 就是 AGA_Graph.uuid，方便观察和查询。注意要同步修改二者
        public AGA_Resources resources = new AGA_Resources();
        public string publishPath;
        public string timelineData;
        public string archiveData; // AGA_Root内容
    }

    internal class AGA_Root {
        public const uint usingFormatVersion = 1;

        public uint formatVersion;
        public AUID uuid; // 文件复制要保证此值换新
        public List<AGA_Graph> graphs;
        public AGA_Blackboard blackboard;


        internal AGA_Root() {
            formatVersion = usingFormatVersion;
            uuid = AUIDGenerator.Gen();
            graphs = new List<AGA_Graph>();
            blackboard = new AGA_Blackboard();
        }

        public int FindGraph(AUID uuid) {
            var index = graphs.FindIndex(x => x.uuid == uuid);
            return index;
        }
    }

    internal class AGA_Graph {
        public string name;
        public AUID uuid; // 文件复制要保证此值换新
        public AUID rootSubGraph;
        public List<AGA_SubGraph> subGraphs = new List<AGA_SubGraph>();

        public AGA_Graph() {
            uuid = AUIDGenerator.Gen();
        }
        public int FindeSubGraph(AUID uuid) {
            var index = subGraphs.FindIndex(x => x.uuid == uuid);
            return index;
        }
    }

    internal class AGA_SubGraph {
        public string name;
        public AUID uuid;
        public AUID rootNode;
        public List<AGANode_NodeBase> nodes;
        public List<AGA_Edge> edges;

        public AGA_SubGraph() {
            uuid = AUIDGenerator.Gen();
            nodes = new List<AGANode_NodeBase>();
            edges = new List<AGA_Edge>();
        }
        public int FindNode(AUID uuid) {
            var index = nodes.FindIndex(x => x.uuid == uuid);
            return index;
        }
        public AGANode_NodeBase FindNextNodeInstance(AUID inputNode, AUID inputPort) {
            var edgeIndex = edges.FindIndex(x => x.inputNode == inputNode && x.inputPort == inputPort);
            if (edgeIndex < 0) {
                D.Exception($"存在端口未正常连接  节点uuid: {inputNode}");
            }
            var outputNodeUuid = edges[edgeIndex].outputNode;
            var outputNodeIndex = FindNode(outputNodeUuid);
            return nodes[outputNodeIndex];
        }

        public int FindEdge(AUID inputNode, AUID inputPort, AUID outputNode, AUID outputPort) {
            var index = edges.FindIndex(x => x.inputNode == inputNode && x.inputPort == inputPort && x.outputNode == outputNode && x.outputPort == outputPort);
            return index;
        }
    }

    internal struct AGA_Edge {
        public AUID inputNode;
        public AUID inputPort;
        public AUID outputNode;
        public AUID outputPort;
        public AGA_Edge(AUID inputNode, AUID inputPort, AUID outputNode, AUID outputPort) {
            this.inputNode = inputNode;
            this.inputPort = inputPort;
            this.outputNode = outputNode;
            this.outputPort = outputPort;
        }
    }


    internal class AGA_Blackboard {
        public struct Entry {
            public AUID uuid;
            public string name;
            public AGABlackboardType type;
        }

        public List<Entry> entries = new List<Entry>();

        public int FindEnry(AUID uuid) {
            var index = entries.FindIndex(x => x.uuid == uuid);
            return index;
        }
        public bool GetEntry(AUID uuid, out Entry entry) {
            var index = FindEnry(uuid);
            if (index >= 0) {
                entry = entries[index];
                return true;
            }
            entry = default;
            return false;
        }

        public bool GetEntryByName(string name, out Entry entry) {
            var index = entries.FindIndex(x => x.name == name);
            if (index >= 0) {
                entry = entries[index];
                return true;
            }
            entry = default;
            return false;
        }
        public Entry[] GetEntriesBySearch(string name) {
            var result = entries.Where(x => x.name.ToLower().Contains(name.ToLower())).ToArray();
            return result;
        }
    }

    public enum AGAResourceType {
        Clip,
        Mask,
    }

    [Serializable]
    public class AGA_Resources {
        [Serializable]
        public struct Entry {
            public AUID uuid;
            public UnityEngine.Object resource;
            public AGAResourceType type;
            public int refCount;
        }

        public List<Entry> entries = new List<Entry>();

    }

}